x86_64: Make 32-bit-hypercall translate area per-vcpu.
authorKeir Fraser <keir@xen.org>
Tue, 16 Nov 2010 14:16:36 +0000 (14:16 +0000)
committerKeir Fraser <keir@xen.org>
Tue, 16 Nov 2010 14:16:36 +0000 (14:16 +0000)
This is a prerequisite for allowing guest descheduling within a
hypercall.

Signed-off-by: Keir Fraser <keir@xen.org>
xen/arch/x86/domain.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/smpboot.c
xen/arch/x86/x86_64/mm.c
xen/include/asm-x86/domain.h
xen/include/asm-x86/x86_64/uaccess.h

index 6cdb6d85c66d97912774052ac1c6e5703efe9b74..13ff47555590042f487849f8e20a4bb11e880e94 100644 (file)
@@ -214,11 +214,19 @@ static int setup_compat_l4(struct vcpu *v)
 {
     struct page_info *pg;
     l4_pgentry_t *l4tab;
+    int rc;
 
     pg = alloc_domheap_page(NULL, MEMF_node(vcpu_to_node(v)));
     if ( pg == NULL )
         return -ENOMEM;
 
+    rc = setup_compat_arg_xlat(v);
+    if ( rc )
+    {
+        free_domheap_page(pg);
+        return rc;
+    }
+
     /* This page needs to look like a pagetable so that it can be shadowed */
     pg->u.inuse.type_info = PGT_l4_page_table|PGT_validated|1;
 
@@ -239,6 +247,7 @@ static int setup_compat_l4(struct vcpu *v)
 
 static void release_compat_l4(struct vcpu *v)
 {
+    free_compat_arg_xlat(v);
     free_domheap_page(pagetable_get_page(v->arch.guest_table));
     v->arch.guest_table = pagetable_null();
     v->arch.guest_table_user = pagetable_null();
index ba0481a13329ca4bf298c69dc7840858fec21558..6bd92ce61c90e9d8dc5588d9c5105727aa9885b6 100644 (file)
@@ -944,9 +944,15 @@ int hvm_vcpu_initialise(struct vcpu *v)
     spin_lock_init(&v->arch.hvm_vcpu.tm_lock);
     INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
 
-    rc = hvm_vcpu_cacheattr_init(v);
+#ifdef CONFIG_COMPAT
+    rc = setup_compat_arg_xlat(v);
     if ( rc != 0 )
         goto fail3;
+#endif
+
+    rc = hvm_vcpu_cacheattr_init(v);
+    if ( rc != 0 )
+        goto fail4;
 
     tasklet_init(&v->arch.hvm_vcpu.assert_evtchn_irq_tasklet,
                  (void(*)(unsigned long))hvm_assert_evtchn_irq,
@@ -971,6 +977,10 @@ int hvm_vcpu_initialise(struct vcpu *v)
 
     return 0;
 
+ fail4:
+#ifdef CONFIG_COMPAT
+    free_compat_arg_xlat(v);
+#endif
  fail3:
     hvm_funcs.vcpu_destroy(v);
  fail2:
@@ -981,6 +991,9 @@ int hvm_vcpu_initialise(struct vcpu *v)
 
 void hvm_vcpu_destroy(struct vcpu *v)
 {
+#ifdef CONFIG_COMPAT
+    free_compat_arg_xlat(v);
+#endif
     tasklet_kill(&v->arch.hvm_vcpu.assert_evtchn_irq_tasklet);
     hvm_vcpu_cacheattr_destroy(v);
     vlapic_destroy(v);
index 365d70a4c47a81e535239077d7fedc72662bc9e3..90b4bfb56cc7c7715fa87171c8ed37fd57d07921 100644 (file)
@@ -627,10 +627,6 @@ static void cpu_smpboot_free(unsigned int cpu)
     xfree(idt_tables[cpu]);
     idt_tables[cpu] = NULL;
 
-#ifdef __x86_64__
-    free_compat_arg_xlat(cpu);
-#endif
-
     order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
 #ifdef __x86_64__
     if ( per_cpu(compat_gdt_table, cpu) )
@@ -690,11 +686,6 @@ static int cpu_smpboot_alloc(unsigned int cpu)
     BUILD_BUG_ON(NR_CPUS > 0x10000);
     gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
 
-#ifdef __x86_64__
-    if ( setup_compat_arg_xlat(cpu, cpu_to_node[cpu]) )
-        goto oom;
-#endif
-
     idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES);
     if ( idt_tables[cpu] == NULL )
         goto oom;
index 883d23fa84203e819d0f41f2e5e702d954bd76e0..1de4e8b03d3305c28c73aa135ffb3003f23e6b6a 100644 (file)
@@ -47,8 +47,6 @@ unsigned int __read_mostly pfn_pdx_hole_shift = 0;
 
 unsigned int __read_mostly m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START;
 
-DEFINE_PER_CPU_READ_MOSTLY(void *, compat_arg_xlat);
-
 /* Top-level master (and idle-domain) page directory. */
 l4_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
     idle_pg_table[L4_PAGETABLE_ENTRIES];
@@ -819,25 +817,30 @@ void __init zap_low_mappings(void)
                      0x10, __PAGE_HYPERVISOR);
 }
 
-int __cpuinit setup_compat_arg_xlat(unsigned int cpu, int node)
+void *compat_arg_xlat_virt_base(void)
+{
+    return current->arch.compat_arg_xlat;
+}
+
+int setup_compat_arg_xlat(struct vcpu *v)
 {
     unsigned int order = get_order_from_bytes(COMPAT_ARG_XLAT_SIZE);
-    unsigned int memflags = node != NUMA_NO_NODE ? MEMF_node(node) : 0;
     struct page_info *pg;
 
-    BUG_ON((PAGE_SIZE << order) != COMPAT_ARG_XLAT_SIZE);
+    pg = alloc_domheap_pages(NULL, order, 0);
+    if ( pg == NULL )
+        return -ENOMEM;
 
-    pg = alloc_domheap_pages(NULL, order, memflags);
-    per_cpu(compat_arg_xlat, cpu) = pg ? page_to_virt(pg) : NULL;
-    return pg ? 0 : -ENOMEM;
+    v->arch.compat_arg_xlat = page_to_virt(pg);
+    return 0;
 }
 
-void __cpuinit free_compat_arg_xlat(unsigned int cpu)
+void free_compat_arg_xlat(struct vcpu *v)
 {
     unsigned int order = get_order_from_bytes(COMPAT_ARG_XLAT_SIZE);
-    if ( per_cpu(compat_arg_xlat, cpu) != NULL )
-        free_domheap_pages(virt_to_page(per_cpu(compat_arg_xlat, cpu)), order);
-    per_cpu(compat_arg_xlat, cpu) = NULL;
+    if ( v->arch.compat_arg_xlat != NULL )
+        free_domheap_pages(virt_to_page(v->arch.compat_arg_xlat), order);
+    v->arch.compat_arg_xlat = NULL;
 }
 
 void cleanup_frame_table(struct mem_hotadd_info *info)
@@ -1009,10 +1012,6 @@ void __init subarch_init_memory(void)
             share_xen_page_with_privileged_guests(page, XENSHARE_readonly);
         }
     }
-
-    if ( setup_compat_arg_xlat(smp_processor_id(),
-                               cpu_to_node[0]) )
-        panic("Could not setup argument translation area");
 }
 
 long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
index 6b4222abed3866568e264300a959cac47ae2ff06..5ff0a06e9871cd38fa21180d7b36b93745b10099 100644 (file)
@@ -436,6 +436,10 @@ struct arch_vcpu
     /* A secondary copy of the vcpu time info. */
     XEN_GUEST_HANDLE(vcpu_time_info_t) time_info_guest;
 
+#ifdef CONFIG_COMPAT
+    void *compat_arg_xlat;
+#endif
+
 } __cacheline_aligned;
 
 /* Shorthands to improve code legibility. */
index c5cb386d2bfeac7dc8a84bc92d90108c4e67a2c7..e35ce28e03f0ffc6e8f095aad156cc96b2ebcfc0 100644 (file)
@@ -1,11 +1,12 @@
 #ifndef __X86_64_UACCESS_H
 #define __X86_64_UACCESS_H
 
-#define COMPAT_ARG_XLAT_VIRT_BASE this_cpu(compat_arg_xlat)
+#define COMPAT_ARG_XLAT_VIRT_BASE compat_arg_xlat_virt_base()
 #define COMPAT_ARG_XLAT_SIZE      (2*PAGE_SIZE)
-DECLARE_PER_CPU(void *, compat_arg_xlat);
-int setup_compat_arg_xlat(unsigned int cpu, int node);
-void free_compat_arg_xlat(unsigned int cpu);
+struct vcpu;
+void *compat_arg_xlat_virt_base(void);
+int setup_compat_arg_xlat(struct vcpu *v);
+void free_compat_arg_xlat(struct vcpu *v);
 #define is_compat_arg_xlat_range(addr, size) ({                               \
     unsigned long __off;                                                      \
     __off = (unsigned long)(addr) - (unsigned long)COMPAT_ARG_XLAT_VIRT_BASE; \